package com.engine4cloud.tdf.supervision.service.impl;

import cn.hutool.core.date.DateUtil;
import com.engine4cloud.tdf.admin.api.dto.AreaQueryDTO;
import com.engine4cloud.tdf.admin.api.dto.SysFileDownloadRequestDTO;
import com.engine4cloud.tdf.admin.api.feign.RemoteAreaService;
import com.engine4cloud.tdf.admin.api.feign.RemoteFileService;
import com.engine4cloud.tdf.admin.api.vo.AreaResultVO;
import com.engine4cloud.tdf.common.core.constant.SecurityConstants;
import com.engine4cloud.tdf.common.core.constant.SupervisionBusinessConstants;
import com.engine4cloud.tdf.common.core.constant.enums.CorFileTypeEnum;
import com.engine4cloud.tdf.common.core.constant.enums.FileBucketNameEnum;
import com.engine4cloud.tdf.common.core.constant.enums.FileDirEnum;
import com.engine4cloud.tdf.common.core.constant.enums.YesNoEnum;
import com.engine4cloud.tdf.common.core.exception.ValidateCodeException;
import com.engine4cloud.tdf.common.core.util.R;
import com.engine4cloud.tdf.common.core.util.RetOps;
import com.engine4cloud.tdf.common.core.util.preview.FileNameExtractorUtils;
import com.engine4cloud.tdf.common.core.util.preview.ImgPreviewModel;
import com.engine4cloud.tdf.common.core.util.preview.PreviewUtils;
import com.engine4cloud.tdf.common.data.tenant.TenantContextHolder;
import com.engine4cloud.tdf.common.data.web.response.PageInfo;
import com.engine4cloud.tdf.common.data.web.response.Params;
import com.engine4cloud.tdf.supervision.dto.query.JzdxFamilySocietyQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxFileQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxLegalInstrumentQueryDTO;
import com.engine4cloud.tdf.supervision.dto.query.JzdxResumeQueryDTO;
import com.engine4cloud.tdf.supervision.dto.result.*;
import com.engine4cloud.tdf.supervision.mapper.JzdxPreviewMapper;
import com.engine4cloud.tdf.supervision.dto.result.*;
import com.engine4cloud.tdf.supervision.service.*;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class JzdxPreviewServiceImpl implements JzdxPreviewService {
    @Resource
    private JzdxFileService fileService;

    @Resource
    private JzdxDepartService departService;

    @Resource
    private JzdxCrimeInfoService crimeInfoService;

    @Resource
    private JzdxInterdictService interdictService;

    @Resource
    private JzdxReportReceiveCaseService reportReceiveCaseService;

    @Resource
    private JzdxFamilySocietyService familySocietyService;

    @Resource
    private JzdxResumeService resumeService;

    @Resource
    private RemoteFileService remoteFileService;

    @Resource
    private RemoteAreaService remoteAreaService;

    @Resource
    private JzdxLegalInstrumentService legalInstrumentService;

    @Resource
    private JzdxPreviewMapper previewMapper;

    @Override
    public byte[] preview(String code) {
        JzdxBaseInfoPreviewResultDTO preview = Optional.ofNullable(this.findPreviewByCode(code))
                .orElseThrow(() -> new ValidateCodeException("矫正对象数据不存在"));

        TenantContextHolder.setTenantSkip();
        R<byte[]> remoteTemplate = remoteFileService.fileBytes(new SysFileDownloadRequestDTO(FileBucketNameEnum.SUPERVISION,
                FileDirEnum.SUPERVISION_CORRECTOR_LEGAL_INSTRUMENT_TEMPLATE,
                SupervisionBusinessConstants.CORRECTOR_BASE_INFORMATION_TEMPLATE_NAME), SecurityConstants.FROM_IN);
        byte[] template = RetOps.of(remoteTemplate)
                .getData()
                .orElse(null);

        R<byte[]> remoteFont = remoteFileService.fileBytes(new SysFileDownloadRequestDTO(FileBucketNameEnum.SUPERVISION,
                FileDirEnum.SUPERVISION_CORRECTOR_LEGAL_INSTRUMENT_TEMPLATE,
                SupervisionBusinessConstants.TEMPLATE_FONT_TTF_NAME), SecurityConstants.FROM_IN);
        byte[] font = RetOps.of(remoteFont)
                .getData()
                .orElse(null);

        if (Objects.isNull(template) || Objects.isNull(font)) {
            return null;
        }

        ImgPreviewModel imageStream = this.getImage(code);
        return PreviewUtils.preview(preview, new ByteArrayInputStream(template), new ByteArrayInputStream(font), imageStream).toByteArray();
    }


    @Override
    public JzdxBaseInfoPreviewResultDTO findPreviewByCode(String code) {
        JzdxBaseInfoPreviewResultDTO result = Optional.ofNullable(previewMapper.findPreviewByCode(code))
                .orElseThrow(() -> new ValidateCodeException("矫正对象数据不存在"));

        //设置照片
        this.setPhoto(code, result);
        //设置具体罪名犯罪类型
        this.setCrimeInfo(code, result);
        //设置法律文书
        this.setLegalInstrument(code, result);
        //设置禁止令
        this.setInterdict(code, result);
        //设置报到情况
        this.setReceive(code, result);
        //设置个人简历
        this.setResumeList(code, result);
        //设置家庭与社会关系
        this.setFamilySociety(code, result);
        //设置户籍地
        result.setJzd(this.setAreaDetail(result.getGdjzdszs(), result.getGdjzdszds(), result.getGdjzdszxq(), result.getGdjzd(), result.getGdjzdmx()));
        //设置居住地
        result.setHjd(this.setAreaDetail(result.getHjszs(), result.getHjszds(), result.getHjszxq(), result.getHjszd(), result.getHjszdmx()));
        //设置执行地
        result.setZxd(this.getPlace(code));
        return result;
    }

    private void setPhoto(String code, JzdxBaseInfoPreviewResultDTO dto) {
        List<JzdxFileResultDTO> photoList = fileService.findList(new JzdxFileQueryDTO(code, CorFileTypeEnum.CORRECTOR_PHOTOGRAPH));
        if (CollectionUtils.isEmpty(photoList)) {
            return;
        }
        dto.setZp(photoList.get(0).getUrl());
    }

    private void setCrimeInfo(String code, JzdxBaseInfoPreviewResultDTO result) {
        List<JzdxCrimeInfoResultDTO> crimeInfoList = crimeInfoService.findDetailList(code);
        result.setFzlx(this.getCrimeType(crimeInfoList));
        result.setJtzm(this.getCrimeName(crimeInfoList));
    }

    private String getCrimeType(List<JzdxCrimeInfoResultDTO> crimeInfoList) {
        if (CollectionUtils.isEmpty(crimeInfoList)) {
            return "";
        }

        return String.join(",", crimeInfoList.stream().map(JzdxCrimeInfoResultDTO::getFzlxmc).collect(Collectors.toSet()));
    }

    private String getCrimeName(List<JzdxCrimeInfoResultDTO> crimeInfoList) {
        if (CollectionUtils.isEmpty(crimeInfoList)) {
            return "";
        }

        return String.join(",", crimeInfoList.stream().map(JzdxCrimeInfoResultDTO::getJtzmmc).toList());
    }

    private void setLegalInstrument(String code, JzdxBaseInfoPreviewResultDTO result) {
        PageInfo<JzdxLegalInstrumentResultDTO> page = legalInstrumentService.pageList(new Params(), new JzdxLegalInstrumentQueryDTO(code));

        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            result.setFlws(String.join(",", page.getRecords().stream().map(record -> DateUtil.formatLocalDateTime(record.getCreateTime()) + " 收到 " + record.getLxmc()).toList()));
        }
    }

    private String setAreaDetail(String provinceCode, String cityCode, String countyCode, String villageAreaId, String detail) {
        AreaResultVO province = null;
        AreaResultVO city = null;
        AreaResultVO county = null;
        AreaResultVO village = null;

        if (StringUtils.isNotEmpty(provinceCode)) {
            R<AreaResultVO> remoteProvince = remoteAreaService.getAreaDetail(new AreaQueryDTO(provinceCode), SecurityConstants.FROM_IN);
            province = RetOps.of(remoteProvince)
                    .getData()
                    .orElse(null);
        }

        if (StringUtils.isNotEmpty(cityCode)) {
            R<AreaResultVO> remoteCity = remoteAreaService.getAreaDetail(new AreaQueryDTO(cityCode), SecurityConstants.FROM_IN);
            city = RetOps.of(remoteCity)
                    .getData()
                    .orElse(null);

        }

        if (StringUtils.isNotEmpty(countyCode)) {
            R<AreaResultVO> remoteCounty = remoteAreaService.getAreaDetail(new AreaQueryDTO(countyCode), SecurityConstants.FROM_IN);
            county = RetOps.of(remoteCounty)
                    .getData()
                    .orElse(null);

        }

        if (StringUtils.isNotEmpty(countyCode) && Objects.nonNull(villageAreaId)) {
            R<AreaResultVO> remoteVillage = remoteAreaService.getAreaDetail(new AreaQueryDTO(countyCode, Long.valueOf(villageAreaId)), SecurityConstants.FROM_IN);
            village = RetOps.of(remoteVillage)
                    .getData()
                    .orElse(null);

        }

        return (Objects.isNull(province) ? "" : province.getName())
                + (Objects.isNull(city) ? "" : city.getName())
                + (Objects.isNull(county) ? "" : county.getName())
                + (Objects.isNull(village) ? "" : village.getName())
                + detail;
    }

    private void setInterdict(String code, JzdxBaseInfoPreviewResultDTO dto) {
        JzdxInterdictResultDTO interdict = interdictService.findLatest(code);

        if (Objects.isNull(interdict)) {
            return;
        }

        dto.setJzlnr(interdict.getJzlnr());
        dto.setJzqxqzrq(interdict.getJzqxksrq() + " 至 " + interdict.getJzqxjsrq());
    }

    private void setReceive(String code, JzdxBaseInfoPreviewResultDTO dto) {
        JzdxReportReceiveCaseResultDTO receive = reportReceiveCaseService.getByCode(code);
        if (Objects.isNull(receive)) {
            return;
        }

        if (Objects.equals(receive.getBdqk(), "01")) {
            dto.setSfzgdsjnbd(YesNoEnum.YES.getDesc());
        } else if (Objects.equals(receive.getBdqk(), "02")) {
            dto.setSfccgdsxbd(YesNoEnum.YES.getDesc());
        } else if (Objects.equals(receive.getBdqk(), "03")) {
            dto.setSfwbdqxlbm(YesNoEnum.YES.getDesc());
        }
    }

    private void setResumeList(String code, JzdxBaseInfoPreviewResultDTO dto) {
        PageInfo<JzdxResumeResultDTO> page = resumeService.pageList(new Params(SupervisionBusinessConstants.CORRECTOR_RESUME_PREVIEW_PAGE_SIZE, SupervisionBusinessConstants.CORRECTOR_RESUME_PREVIEW_PAGE_CURRENT),
                new JzdxResumeQueryDTO(code));

        if (CollectionUtils.isEmpty(page.getRecords())) {
            return;
        }

        if (!page.getRecords().isEmpty()) {
            JzdxResumeResultDTO resumeFirst = page.getRecords().get(0);
            dto.setQzr1(resumeFirst.getQs() + " 至 " + resumeFirst.getZr());
            dto.setSzdw1(resumeFirst.getSzdw());
            dto.setZw1(resumeFirst.getZwmc());
        }

        if (page.getRecords().size() >= 2) {
            JzdxResumeResultDTO resumeSecond = page.getRecords().get(1);
            dto.setQzr2(resumeSecond.getQs() + " 至 " + resumeSecond.getZr());
            dto.setSzdw2(resumeSecond.getSzdw());
            dto.setZw2(resumeSecond.getZwmc());
        }

        if (page.getRecords().size() >= 3) {
            JzdxResumeResultDTO resumeThird = page.getRecords().get(2);
            dto.setQzr3(resumeThird.getQs() + " 至 " + resumeThird.getZr());
            dto.setSzdw3(resumeThird.getSzdw());
            dto.setZw3(resumeThird.getZwmc());
        }

        if (page.getRecords().size() >= 4) {
            JzdxResumeResultDTO resumeFourth = page.getRecords().get(3);
            dto.setQzr4(resumeFourth.getQs() + " 至 " + resumeFourth.getZr());
            dto.setSzdw4(resumeFourth.getSzdw());
            dto.setZw4(resumeFourth.getZwmc());
        }

        if (page.getRecords().size() >= 5) {
            JzdxResumeResultDTO resumeFifth = page.getRecords().get(4);
            dto.setQzr5(resumeFifth.getQs() + " 至 " + resumeFifth.getZr());
            dto.setSzdw5(resumeFifth.getSzdw());
            dto.setZw5(resumeFifth.getZwmc());
        }
    }

    private void setFamilySociety(String code, JzdxBaseInfoPreviewResultDTO dto) {
        PageInfo<JzdxFamilySocietyResultDTO> page = familySocietyService.pageList(new Params(SupervisionBusinessConstants.CORRECTOR_FAMILY_SOCIETY_PREVIEW_PAGE_SIZE, SupervisionBusinessConstants.CORRECTOR_FAMILY_SOCIETY_PREVIEW_PAGE_CURRENT),
                new JzdxFamilySocietyQueryDTO(code));

        if (CollectionUtils.isEmpty(page.getRecords())) {
            return;
        }

        if (!page.getRecords().isEmpty()) {
            JzdxFamilySocietyResultDTO familySocietyFirst = page.getRecords().get(0);
            dto.setXm1(familySocietyFirst.getXm());
            dto.setGx1(familySocietyFirst.getGxmc());
            dto.setGzdw1(familySocietyFirst.getSzdw());
            dto.setLxdh1(familySocietyFirst.getLxdh());
        }

        if (page.getRecords().size() >= 2) {
            JzdxFamilySocietyResultDTO familySocietySecond = page.getRecords().get(1);
            dto.setXm2(familySocietySecond.getXm());
            dto.setGx2(familySocietySecond.getGxmc());
            dto.setGzdw2(familySocietySecond.getSzdw());
            dto.setLxdh2(familySocietySecond.getLxdh());
        }

        if (page.getRecords().size() >= 3) {
            JzdxFamilySocietyResultDTO familySocietyThird = page.getRecords().get(2);
            dto.setXm3(familySocietyThird.getXm());
            dto.setGx3(familySocietyThird.getGxmc());
            dto.setGzdw3(familySocietyThird.getSzdw());
            dto.setLxdh3(familySocietyThird.getLxdh());
        }

        if (page.getRecords().size() >= 4) {
            JzdxFamilySocietyResultDTO familySocietyFourth = page.getRecords().get(3);
            dto.setXm4(familySocietyFourth.getXm());
            dto.setGx4(familySocietyFourth.getGxmc());
            dto.setGzdw4(familySocietyFourth.getSzdw());
            dto.setLxdh4(familySocietyFourth.getLxdh());
        }

        if (page.getRecords().size() >= 5) {
            JzdxFamilySocietyResultDTO familySocietyFifth = page.getRecords().get(4);
            dto.setXm5(familySocietyFifth.getXm());
            dto.setGx5(familySocietyFifth.getGxmc());
            dto.setGzdw5(familySocietyFifth.getSzdw());
            dto.setLxdh5(familySocietyFifth.getLxdh());
        }
    }

    private String getPlace(String code) {
        JzdxDepartResultDTO depart = departService.findByCode(code);
        if (Objects.isNull(depart)) {
            return "";
        }

        return (StringUtils.isEmpty(depart.getJzryszsftmc()) ? "" : depart.getJzryszsftmc())
                + (StringUtils.isEmpty(depart.getJzryszdssfjmc()) ? "" : depart.getJzryszdssfjmc())
                + (StringUtils.isEmpty(depart.getJzryszqxsfjmc()) ? "" : depart.getJzryszqxsfjmc());
    }

    private ImgPreviewModel getImage(String code) {
        ImgPreviewModel imageStream = null;
        List<JzdxFileResultDTO> photoList = fileService.findList(new JzdxFileQueryDTO(code, CorFileTypeEnum.CORRECTOR_PHOTOGRAPH));
        if (CollectionUtils.isNotEmpty(photoList)) {

            JzdxFileResultDTO photo = photoList.get(0);
            String fileName = FileNameExtractorUtils.extract(photo.getUrl());

            if (StringUtils.isNotEmpty(fileName)) {
                R<byte[]> remoteImage = remoteFileService.fileBytes(new SysFileDownloadRequestDTO(FileBucketNameEnum.SUPERVISION,
                        FileDirEnum.SUPERVISION_CORRECTOR_PHOTOGRAPH,
                        fileName), SecurityConstants.FROM_IN);
                byte[] image = RetOps.of(remoteImage)
                        .getData()
                        .orElse(null);

                if (Objects.nonNull(image)) {
                    imageStream = new ImgPreviewModel(image,
                            SupervisionBusinessConstants.CORRECTOR_PREVIEW_IMAGE_X,
                            SupervisionBusinessConstants.CORRECTOR_PREVIEW_IMAGE_Y,
                            SupervisionBusinessConstants.CORRECTOR_PREVIEW_IMAGE_WIDTH,
                            SupervisionBusinessConstants.CORRECTOR_PREVIEW_IMAGE_HEIGHT);
                }
            }
        }

        return imageStream;
    }

}
